#include <string.h>

#include "log.h"
#include "udp_server.h"


#define FAST_CONBLE_MASK_LEN     13

/*静态变量*/
static uint16_t send_msg_seq = 1;  //需要为0的包好像不处理

/**
 * @description: 发送URL请求
 * @return {*}  成功：发送字节数
 *              失败：-1
 */
int FastConbleUrlRequest(void)
{
    log_debug("send URL_REQ\n");
    message_head_t response_head = GenerateHead(URL_REQ, send_msg_seq++);
    return UdpSendtoRemote((message_t *)&response_head, sizeof(response_head));
}

/**
 * @description: 发送短地址控制请求
 * @param {uint16_t} short_addr 短地址
 * @param {uint8_t *} data 控制数据包
 * @param {uint16_t *} data_len 控制数据包长度
 * @return {*}  成功：发送字节数
 *              失败：-1
 */
int FastConbleShortAddrControl(uint16_t short_addr, uint8_t *data, uint16_t data_len)
{
    log_debug("send SHORT_ADDR_CTRL_REQ\n");

    message_head_t response_head = GenerateHead(SHORT_ADDR_CTRL_REQ, send_msg_seq++);

    message_t send_message;
    memset(&send_message, 0, sizeof(message_t));

    // 复制头部信息
    memcpy(&(send_message.head), &response_head, sizeof(response_head));
    
    // 复制body信息
    //2字节地址
    send_message.body[0] = short_addr & 0xff;
    send_message.body[1] = (short_addr>>8) & 0xff;
    //数据信息
    memcpy(&(send_message.body[2]), data, data_len);
    //数据长度加上地址长度
    data_len += 2;

    printf("con data:\n");
    for(int i=0; i<sizeof(response_head)+data_len; i++)
    {
        printf("%02x ", *((uint8_t *)&send_message+i));
    }
    printf("\n");
    printf("%d\n", sizeof(response_head)+data_len);
    return UdpSendtoRemote(&send_message, sizeof(response_head)+data_len);
}

/**
 * @description: 发送场景控制请求
 * @param {uint32_t} scene_id 场景ID
 * @return {*}  成功：发送字节数
 *              失败：-1
 */
int FastConbleSceneControl(uint32_t scene_id)
{
    log_debug("send SCENE_CTRL_REQ\n");

    message_head_t response_head = GenerateHead(SCENE_CTRL_REQ, send_msg_seq++);

    message_t send_message;
    memset(&send_message, 0, sizeof(message_t));

    // 复制头部信息
    memcpy(&(send_message.head), &response_head, sizeof(response_head));
    
    // 复制body信息
    send_message.body[2] = scene_id & 0xff;
    send_message.body[1] = (scene_id >> 8) & 0xff;
    send_message.body[0] = (scene_id >> 16) & 0xff;

    return UdpSendtoRemote(&send_message, sizeof(response_head)+3);
}

/**
 * @description: 发送组控制请求
 * @param {uint32_t} scene_id 场景ID
 * @return {*}  成功：发送字节数
 *              失败：-1
 */
int FastConbleGroupControl(uint8_t group_addr, uint16_t device_type, uint8_t *data, uint16_t data_len)
{
    log_debug("send GROUP_CTRL_REQ, %d\n", send_msg_seq);

    message_head_t response_head = GenerateHead(GROUP_CTRL_REQ, send_msg_seq++);

    message_t send_message;
    memset(&send_message, 0, sizeof(message_t));

    // 复制头部信息
    memcpy(&send_message.head, &response_head, sizeof(response_head));
    
    // 复制body信息
    send_message.body[0] = group_addr;
    send_message.body[1] = (device_type >> 8) & 0xff;
    send_message.body[2] = device_type & 0xff;

    memcpy(&send_message.body[3], data, data_len);

    return UdpSendtoRemote(&send_message, sizeof(response_head)+3+data_len);
}

int FastConbleTriggerDataReport(uint8_t delay_max, uint16_t short_addr, uint8_t *mask)
{
    log_debug("send TRIGGER_DEV_STA_REPORT_REQ\n");

    message_head_t response_head = GenerateHead(TRIGGER_DEV_STA_REPORT_REQ, send_msg_seq++);

    message_t send_message;
    memset(&send_message, 0, sizeof(message_t));

    // 复制头部信息
    memcpy(&send_message.head, &response_head, sizeof(response_head));
    
    // 复制body信息
    uint8_t data[3] = {0};
    data[0] = delay_max & 0xff;

    data[1] = (short_addr >> 8) & 0xff;//大端
    data[2] = short_addr & 0xff;
    
    memcpy(send_message.body, data, sizeof(data));
    memcpy((send_message.body)+sizeof(data), mask, FAST_CONBLE_MASK_LEN);

    return UdpSendtoRemote(&send_message, sizeof(response_head)+sizeof(data)+FAST_CONBLE_MASK_LEN);
}

/**
 * @description: 设置临时分组
 * @param {uint8_t} group_id 临时分组ID
 * @param {uint16_t} start_addr 起始短地址
 * @param {uint16_t} cookie 用来控制临时分组分包和清除
 * @param {uint8_t} mask 短地址掩码
 * @return {*}  成功：发送字节数
 *              失败：-1
 */
int FastConbleSetTempGroup(uint8_t group_id, uint16_t start_addr, uint16_t cookie, uint8_t *mask)
{
    log_debug("send SET_TEMP_GROUP_REQ\n");

    message_head_t response_head = GenerateHead(SET_TEMP_GROUP_REQ, send_msg_seq++);

    message_t send_message;
    memset(&send_message, 0, sizeof(message_t));

    // 复制头部信息
    memcpy(&send_message.head, &response_head, sizeof(response_head));
    
    // 复制body信息
    uint8_t devdata[5+FAST_CONBLE_MASK_LEN] = {0};
    devdata[0] = group_id;
    devdata[1] = start_addr & 0xff;
    devdata[2] = (start_addr >> 8) & 0xff;
    devdata[3] = cookie & 0xff;
    devdata[4] = (cookie >> 8) & 0xff;
    memcpy(&devdata[5], mask, FAST_CONBLE_MASK_LEN);
    memcpy(send_message.body, devdata, sizeof(devdata));

    return UdpSendtoRemote(&send_message, sizeof(response_head)+sizeof(devdata));
}

/**
 * @description: UDP包应答
 * @param {enum BLE_TYPE} 包类型
 * @param {uint16_t} 应答序号
 * @return {*}  成功：发送字节数
 *              失败：-1
 */
int FastConbleAck(enum BLE_TYPE type, uint16_t seq)
{
    uint8_t msg_len = 0;
    message_head_t response_head = GenerateHead(type, seq);
    // 创建响应消息
    // 分配内存给 message_t 结构体
    message_t send_message;
    memset(&send_message, 0, sizeof(message_t));

    memcpy(&send_message.head, &response_head, sizeof(response_head));

    /*probe和心跳响应要返回MAC地址，其他响应不需要*/
    if ((type == PROBE_ACK) || (type == HEARTBEAT_ACK))
    {
        msg_len = ADDR_LEN;
        memcpy(send_message.body, g_mac_addr, ADDR_LEN);
    } 
    // printf("type [%d] seq [%X]\n", type, seq);
    // printf("package content [ ");
    // for (int i=0; i<(sizeof(response_head)+msg_len); i++)
    //     printf("%02X ", ((uint8_t *)send_message)[i]);
    // printf("]\n");

    return UdpSendtoRemote(&send_message, sizeof(response_head)+msg_len);
}

